package com.ybkj.daijia.api.checker;

import com.ybkj.daijia.DateTimeUtils;
import com.ybkj.daijia.Setting;
import com.ybkj.daijia.serverUtils.SettingUtils;
import com.ybkj.daijia.config.PassengerApi;
import com.ybkj.daijia.server.mapper.DriverMapper;
import com.ybkj.daijia.server.mapper.DriverPaymentsRecordMapper;
import com.ybkj.daijia.server.mapper.DriverRebateEnchashmentMapper;
import com.ybkj.daijia.server.mapper.DriverRebatePaymentRecordMapper;
import com.ybkj.daijia.server.mc.Passenger;
import com.ybkj.daijia.server.model.Driver;
import com.ybkj.daijia.server.model.DriverPaymentsRecord;
import com.ybkj.daijia.server.model.DriverRebateEnchashment;
import com.ybkj.daijia.server.model.DriverRebatePaymentRecord;
import com.ybkj.daijia.server.service.DriverService;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author zhyu
 * @date 2019-08-07 11:04:04
 */
@Service
public class CheckDriverServiceImpl implements CheckDriverService {

    public static final int REBATE_MONEY = 1;
    @Autowired
    private DriverMapper driverMapper;
    @Autowired
    private DriverRebatePaymentRecordMapper driverRebatePaymentRecordMapper;
    @Autowired
    private DriverRebateEnchashmentMapper driverRebateEnchashmentMapper;
    @Autowired
    private DriverPaymentsRecordMapper driverPaymentsRecordMapper;
    @Autowired
    private PassengerApi passengerApi;
    @Autowired
    private SettingUtils settingUtils;
    @Autowired
    private DriverService driverService;
    private Set set = new HashSet();

    {
        set.add(53L);
        set.add(120L);
        set.add(38L);
        set.add(52L);
        set.add(110L);
        set.add(44L);
    }

    @Override
    public List<List<String>> checkDriverRabateMoney() {
        List<Driver> drivers = driverMapper
            .selectDriverList(null, null, null, null, null, null, null, null, null, null, null,
                null, null, null, null);
        List<List<String>> lists = new ArrayList<>();
        String[] head = new String[]{"司机id", "username", "realname", "司机账户现有的推荐金额", "司机介绍的客户数量",
            "根据客户数量应得的金额", "司机账户明细中的推荐记录",
            "司机推荐明细中的推荐记录", "司机已提现金额", "错误", "sql"};
        lists.add(Arrays.asList(head));
        for (int i = 0; i < drivers.size(); i++) {
            checkSingleDriverRebateMoney(drivers.get(i), lists);
        }
        return lists;
    }

    public Map<Long, List<DriverPaymentsRecord>> partById(List<DriverPaymentsRecord> data) {
        Map<Long, List<DriverPaymentsRecord>> maps = new HashMap<>();
        for (DriverPaymentsRecord dr : data) {
            Long driverId = dr.getDriverId();
            if (maps.containsKey(driverId)) {
                maps.get(driverId).add(dr);
            } else {
                List<DriverPaymentsRecord> list = new ArrayList<>();
                list.add(dr);
                maps.put(driverId, list);
            }
        }
        return maps;
    }

    @Transactional(rollbackFor = Exception.class)
    public List<List<String>> changeDriverRabteInDriverPaymentToDriverRebatePayment2() {
        List<DriverPaymentsRecord> list = driverPaymentsRecordMapper
            .select(null, DriverPaymentsRecord.RECHARGE_TYPE_REBATE_REWARD, null, null, null, null,
                null);
        List<List<String>> datas = new ArrayList<>();
        Map<Long, List<DriverPaymentsRecord>> maps = partById(list);
        datas.add(Arrays.asList(new String[]{"司机id", "username", "realname", "金钱", "日期", "乘客电话",
            "修改原记录recordType类型sql|总额sql", "减少余额sql",
            "增加推荐奖励记录sql", "增加推荐奖励sql"}));
        Set<Map.Entry<Long, List<DriverPaymentsRecord>>> entries = maps.entrySet();
        String memo = "系统半自动转推荐奖励的余额进入推荐红包";
        Setting setting = settingUtils.get();
        for (Map.Entry<Long, List<DriverPaymentsRecord>> entry : entries) {

            Long key = entry.getKey();
            if (set.contains(key)) {
                System.out.println("key---------");
            }
            List<DriverPaymentsRecord> value = entry.getValue();
            if (value.size() > 0) {
                DriverPaymentsRecord dpr = new DriverPaymentsRecord();
                Date now = new Date();
                dpr.setHappend(now);
                dpr.setDriverId(key);
                BigDecimal money = BigDecimal
                    .valueOf(value.size() * setting.getDriverRebateMoney());
                dpr.setMoney(money.negate());
                dpr.setRcType(DriverPaymentsRecord.DIFFERENT_NEGATIVE);
                dpr.setRecordType(DriverPaymentsRecord.CHANGE_MONEY_TO_REBATE);
                dpr.setMemo(memo);

//                DriverRebatePaymentRecord drpr1 = new DriverRebatePaymentRecord();
//                drpr1.setDriverId(key);
//                drpr1.setMoney(money);
//                drpr1.setOperating(DriverRebatePaymentRecord.OPERATING_SYS);
//                drpr1.setRecordType(DriverRebatePaymentRecord.RECHARGE_TYPE_REBATE);
//                drpr1.setMemo(memo);

                for (DriverPaymentsRecord driverPaymentsRecord : value) {

                    dpr.setDriverRealName(driverPaymentsRecord.getDriverRealName());
                    dpr.setDriverUserName(driverPaymentsRecord.getDriverUserName());
                    dpr.setDriverPhone(driverPaymentsRecord.getDriverPhone());

                    List<String> data = new ArrayList<>();
                    data.add(String.valueOf(driverPaymentsRecord.getDriverId()));
                    data.add(driverPaymentsRecord.getDriverUserName());
                    data.add(driverPaymentsRecord.getDriverRealName());
                    data.add(driverPaymentsRecord.getMoney().toString());
                    data.add(DateTimeUtils.DATE_FORMAT_DATE_yyyyMMddHHmmss
                        .format(driverPaymentsRecord.getHappend()));
                    data.add(driverPaymentsRecord.getPassengerPhone());

                    String updateRecordSql1 =
                        "update summer.dj_driver_payments_record set recordType = 'reb_reward1' where id = "
                            + dpr.getId();

                    data.add(driverPaymentsRecord.getPassengerPhone());
                    data.add(driverPaymentsRecord.getPassengerPhone());
                    data.add(driverPaymentsRecord.getPassengerPhone());
                    datas.add(data);

                    DriverRebatePaymentRecord drpr = new DriverRebatePaymentRecord();
                    drpr.setDriverId(driverPaymentsRecord.getDriverId());
                    drpr.setMoney(driverPaymentsRecord.getMoney());
                    drpr.setPassengerPhone(driverPaymentsRecord.getPassengerPhone());
                    drpr.setOperating(DriverRebatePaymentRecord.OPERATING_SYS);
                    drpr.setRecordType(DriverRebatePaymentRecord.RECHARGE_TYPE_REBATE);
                    drpr.setMemo(memo);
//                    driverService.changeMoneyByDriverRebatePaymenrecord(drpr);

//                    driverPaymentsRecordMapper.deleteByPrimaryKey(driverPaymentsRecord.getId());
                }
                String updateRecordSql2 =
                    "  insert into dj_driver_payments_record (driverId, driverUserName, driverRealName, driverPhone, driverCompanyId,\n"
                        +
                        "        money, afterMoney,\n" +
                        "        memo, orderId, orderNumber, orderType, orderCompanyId, recordType, infoFeeType, operating, rcType, happend,\n"
                        +
                        "        created, updated)\n" +
                        "        values\n" +
                        "        (#{driverId},#{driverUserName},#{driverRealName},#{driverPhone},#{driverCompanyId},#{money},#{afterMoney},\n"
                        +
                        "        #{memo},#{orderId},#{orderNumber},#{orderType},#{orderCompanyId},#{recordType},#{infoFeeType},#{operating},#{rcType},#{happend},now(),now())";
                String subMoneySql =
                    "update summer.dj_driver set virtual = virtual - " + money.toString()
                        + " where driverId = " + key;

//                driverService.changeMoneyByDriverPaymenrecord(dpr);
//                driverService.changeMoneyByDriverRebatePaymenrecord(drpr1);
            }
        }

        return datas;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<List<String>> changeDriverRabteInDriverPaymentToDriverRebatePayment() {
        List<DriverPaymentsRecord> list = driverPaymentsRecordMapper
            .select(null, DriverPaymentsRecord.RECHARGE_TYPE_REBATE_REWARD, null, null, null, null,
                null);
        List<List<String>> datas = new ArrayList<>();
        Map<Long, List<DriverPaymentsRecord>> maps = partById(list);
        datas.add(Arrays.asList(new String[]{"司机id", "username", "realname", "金钱", "日期", "乘客电话"}));
        Set<Map.Entry<Long, List<DriverPaymentsRecord>>> entries = maps.entrySet();
        String memo = "系统半自动转推荐奖励的余额进入推荐红包";
        Setting setting = settingUtils.get();
        for (Map.Entry<Long, List<DriverPaymentsRecord>> entry : entries) {

            Long key = entry.getKey();
            if (set.contains(key)) {
                System.out.println("key---------");
            }
            List<DriverPaymentsRecord> value = entry.getValue();
            if (value.size() > 0) {
                DriverPaymentsRecord dpr = new DriverPaymentsRecord();
                Date now = new Date();
                dpr.setHappend(now);
                dpr.setDriverId(key);
                BigDecimal money = BigDecimal
                    .valueOf(value.size() * setting.getDriverRebateMoney());
                dpr.setMoney(money.negate());
                dpr.setRcType(DriverPaymentsRecord.DIFFERENT_NEGATIVE);
                dpr.setRecordType(DriverPaymentsRecord.CHANGE_MONEY_TO_REBATE);
                dpr.setMemo(memo);

//                DriverRebatePaymentRecord drpr1 = new DriverRebatePaymentRecord();
//                drpr1.setDriverId(key);
//                drpr1.setMoney(money);
//                drpr1.setOperating(DriverRebatePaymentRecord.OPERATING_SYS);
//                drpr1.setRecordType(DriverRebatePaymentRecord.RECHARGE_TYPE_REBATE);
//                drpr1.setMemo(memo);

                for (DriverPaymentsRecord driverPaymentsRecord : value) {

                    dpr.setDriverRealName(driverPaymentsRecord.getDriverRealName());
                    dpr.setDriverUserName(driverPaymentsRecord.getDriverUserName());
                    dpr.setDriverPhone(driverPaymentsRecord.getDriverPhone());

                    List<String> data = new ArrayList<>();
                    data.add(String.valueOf(driverPaymentsRecord.getDriverId()));
                    data.add(driverPaymentsRecord.getDriverUserName());
                    data.add(driverPaymentsRecord.getDriverRealName());
                    data.add(driverPaymentsRecord.getMoney().toString());
                    data.add(DateTimeUtils.DATE_FORMAT_DATE_yyyyMMddHHmmss
                        .format(driverPaymentsRecord.getHappend()));
                    data.add(driverPaymentsRecord.getPassengerPhone());
                    datas.add(data);

                    DriverRebatePaymentRecord drpr = new DriverRebatePaymentRecord();
                    drpr.setDriverId(driverPaymentsRecord.getDriverId());
                    drpr.setMoney(driverPaymentsRecord.getMoney());
                    drpr.setPassengerPhone(driverPaymentsRecord.getPassengerPhone());
                    drpr.setOperating(DriverRebatePaymentRecord.OPERATING_SYS);
                    drpr.setRecordType(DriverRebatePaymentRecord.RECHARGE_TYPE_REBATE);
                    drpr.setMemo(memo);
                    driverService.changeMoneyByDriverRebatePaymenrecord(drpr);
                    driverPaymentsRecord.setMemo("修改入推荐金额,本记录已作废");
                    driverPaymentsRecord.setAfterMoney(null);
                    driverPaymentsRecord
                        .setRecordType(DriverPaymentsRecord.RECHARGE_TYPE_REBATE_REWARD + "1");
                    driverPaymentsRecordMapper.updateByPrimaryKey(driverPaymentsRecord);
                }
                driverService.changeMoneyByDriverPaymenrecord(dpr);
            }
        }

        return datas;
    }

    private void checkSingleDriverRebateMoney(Driver driver, List<List<String>> lists) {
        BigDecimal rebateMoney = driver.getRebateMoney();//推荐奖励
        List<DriverPaymentsRecord> paymentsRecords = driverPaymentsRecordMapper
            .selectByEmploy(driver.getId(), DriverPaymentsRecord.RECHARGE_TYPE_REBATE_REWARD, null,
                null, null, null, null);
        BigDecimal t_paymentRecords = BigDecimal.ZERO;//司机明细中的推荐奖励记录
        for (int i = 0; i < paymentsRecords.size(); i++) {
            t_paymentRecords = t_paymentRecords.add(paymentsRecords.get(i).getMoney());
        }
        List<DriverRebatePaymentRecord> rebatePaymentRecords = driverRebatePaymentRecordMapper
            .listIndexPayments(null, null, driver.getId(),
                DriverRebatePaymentRecord.RECHARGE_TYPE_REBATE, null, null);
        BigDecimal t_rebateRecords = BigDecimal.ZERO;//推荐明细中的奖励记录
        for (int i = 0; i < rebatePaymentRecords.size(); i++) {
            t_rebateRecords = t_rebateRecords.add(rebatePaymentRecords.get(i).getMoney());
        }
        Long pCount = passengerApi.countPassengerByIntroducer(driver.getUsername(), null,
            Passenger.INTRODUCE_TYPE_DRIVER);//推荐人数
        BigDecimal shouldMoney = new BigDecimal(REBATE_MONEY * pCount);//按照人数总计应发的金额
        List<DriverRebateEnchashment> driverRebateEnchashments = driverRebateEnchashmentMapper
            .selectBylist(driver.getId(), null);
        BigDecimal enchashMents = BigDecimal.ZERO;//提现金额
        for (int i = 0; i < driverRebateEnchashments.size(); i++) {
            DriverRebateEnchashment en = driverRebateEnchashments.get(i);
            if (en.getStatus().equals(DriverRebateEnchashment.STATUS_SUCCESS) || en.getStatus()
                .equals(DriverRebateEnchashment.STATUS_WAIT)) {
                enchashMents = enchashMents.add(en.getOpRebateMoney());
            }
        }
        BigDecimal recordOkC = t_paymentRecords.add(t_rebateRecords).subtract(shouldMoney);
        BigDecimal moneyOkC = shouldMoney.subtract(enchashMents).subtract(t_paymentRecords)
            .subtract(rebateMoney);
        if (0 != recordOkC.doubleValue() || 0 != moneyOkC.doubleValue()) {
            if (driver.getId() == 38) {
                System.out.println();
            }
            Map<ErrorType, String> errorTypes = new HashMap<>();
            if (moneyOkC.doubleValue() > 0) {
                errorTypes.put(ErrorType.MONEY_LESS, moneyOkC.toString());
            } else if (moneyOkC.doubleValue() < 0) {
                errorTypes.put(ErrorType.MONEY_MORE, moneyOkC.toString());
            }

            if (recordOkC.doubleValue() > 0) {
                errorTypes.put(ErrorType.RECORD_MORE, recordOkC.toString());
            } else if (recordOkC.doubleValue() < 0) {
                errorTypes.put(ErrorType.RECORD_MORE, recordOkC.toString());
            }
            List<String> list = new ArrayList<>();
            list.add(String.valueOf(driver.getId()));
            list.add(driver.getUsername());
            list.add(driver.getRealname());
            list.add(driver.getRebateMoney().toString());
            list.add(String.valueOf(pCount));
            list.add(shouldMoney.toString());
            list.add(t_paymentRecords.toString());
            list.add(t_rebateRecords.toString());
            list.add(enchashMents.toString());
            list.add(ErrorType.printf(errorTypes));
            String sql = null;
            if (errorTypes.containsKey(ErrorType.MONEY_LESS)) {
                sql = "update summer.dj_driver set rebateMoney = rebateMoney + " + moneyOkC
                    .doubleValue() + " where id = " + driver.getId() + ";";
            } else if (errorTypes.containsKey(ErrorType.MONEY_MORE)) {
                sql = "update summer.dj_driver set rebateMoney = rebateMoney - " + moneyOkC.negate()
                    .doubleValue() + " where id = " + driver.getId() + ";";
            }

            list.add(sql);
            lists.add(list);
        }
    }

    public enum ErrorType {
        RECORD_MORE(1, "记录数多于推荐人数"),
        RECORD_LESS(2, "记录数少于推荐人数"),
        MONEY_LESS(3, "给的钱少了"),
        MONEY_MORE(4, "给的钱多了"),
        ;

        private ErrorType next;
        private int errorCode;
        private String errorWord;

        ErrorType(int errorCode, String errorWord) {
            this.errorCode = errorCode;
            this.errorWord = errorWord;
        }

        public static String printf(Map<ErrorType, String> errorMaps) {
            String word = "";
            Set<ErrorType> errors = errorMaps.keySet();
            if (null != errors && errors.size() != 0) {
                for (ErrorType errorType : errors) {
                    word += errorType.getErrorWord() + ";";
                }
            }
            return word;
        }

        public ErrorType getNext() {
            return next;
        }

        public int getErrorCode() {
            return errorCode;
        }

        public String getErrorWord() {
            return errorWord;
        }
    }
}
